﻿using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;
using Neturion.Dados;
using Neturion.IRepositorios;

namespace Neturion.Repositorios
{
    public class RepositorioAssunto : IRepositorioAssunto
    {
        public Assunto Inserir(Assunto assunto)
        {
            assunto.FimVigencia = assunto.FimVigencia.HasValue
                                    ? assunto.FimVigencia.GetValueOrDefault().Date
                                    : assunto.FimVigencia;
            assunto.InicioVigencia = assunto.InicioVigencia.HasValue
                                        ? assunto.InicioVigencia.GetValueOrDefault().Date
                                        : assunto.InicioVigencia;

            foreach (AssuntoProcedimento assuntoProcedimento in assunto.ListaAssuntoProcedimentos)
            {
                assuntoProcedimento.Assunto = assunto;
            }

            //foreach (MotivoProtocolo motivoProtocolo in assunto.ListaMotivosProtocolo)
            //{
            //    motivoProtocolo.AdicionarAssunto(assunto);
            //}

            GerenciadorBDConfigs.Instance.SessaoAtual().Save(assunto);
            return assunto;
        }

        public Assunto Atualizar(Assunto assunto)
        {
            Assunto tmpAssunto = ObterPorId(assunto.AssuntoId);
            // Atribuicao dos valores do objeto da memoria para o objeto obtido no banco de dados
            tmpAssunto.Codigo = assunto.Codigo;
            tmpAssunto.DataCadastro = assunto.DataCadastro.Date;
            tmpAssunto.Descricao = assunto.Descricao;
            tmpAssunto.FimVigencia = assunto.FimVigencia.HasValue
                                    ? assunto.FimVigencia.GetValueOrDefault().Date
                                    : assunto.FimVigencia;
            tmpAssunto.InicioVigencia = assunto.InicioVigencia.HasValue
                                        ? assunto.InicioVigencia.GetValueOrDefault().Date
                                        : assunto.InicioVigencia;
            tmpAssunto.FuncionarioResponsavel = assunto.FuncionarioResponsavel;
            tmpAssunto.NeturionLog = assunto.NeturionLog;
            tmpAssunto.Observacao = assunto.Observacao;
            tmpAssunto.PrazoResolucao = assunto.PrazoResolucao;
            tmpAssunto.SetorResponsavel = assunto.SetorResponsavel;
            tmpAssunto.TipoAssunto = assunto.TipoAssunto;
            
            tmpAssunto.ListaAssuntoProcedimentos.Clear();
            foreach (AssuntoProcedimento assuntoProcedimento in assunto.ListaAssuntoProcedimentos)
            {
                tmpAssunto.AdicionarProcedimento(assuntoProcedimento);
            }

            tmpAssunto.ListaMotivosProtocolo.Clear();
            foreach (MotivoProtocolo motivoProtocolo in assunto.ListaMotivosProtocolo)
            {
                tmpAssunto.AdicionarMotivoProtocolo(motivoProtocolo);
            }

            GerenciadorBDConfigs.Instance.SessaoAtual().Merge(tmpAssunto);
            return tmpAssunto;
        }

        public void Excluir(Assunto assunto)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Delete(assunto);
        }

        public IList<Assunto> ObterTodos()
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Assunto));
            return criteria.List<Assunto>() as List<Assunto>;
        }

        public IList<Assunto> ObterTodos(int inicio, int quantidade, int quantidadeMinima, string codigo, string descricao, 
        TipoAssunto tipoAssunto, Setor setor, Funcionario funcionario, DateTime? inicioVigenciaDe, DateTime? inicioVigenciaAte, 
            DateTime? fimVigenciaDe, DateTime? fimVigenciaAte)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            IList<Assunto> list;
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Assunto))

               .SetFirstResult(inicio).SetMaxResults(quantidade);

            if (!string.IsNullOrEmpty(codigo))
            {
                criteria.Add(Restrictions.Eq("Codigo", codigo));
            }

            if (!string.IsNullOrEmpty(descricao))
            {
                criteria.Add(Restrictions.Like("Descricao", descricao, MatchMode.Anywhere));
            }

            if (tipoAssunto!= null)
            {
                criteria.Add(Restrictions.Eq("TipoAssunto", tipoAssunto));
            }

            if (setor != null)
            {
                criteria.Add(Restrictions.Eq("SetorResponsavel", setor));
            }

            if (funcionario != null)
            {
                criteria.Add(Restrictions.Eq("FuncionarioResponsavel", funcionario));
            }

            if (inicioVigenciaDe.HasValue)
            {
                criteria.Add(inicioVigenciaAte.HasValue
                    ? Restrictions.Between("InicioVigencia", inicioVigenciaDe.Value.Date, inicioVigenciaAte.Value.Date)
                    : Restrictions.Eq("InicioVigencia", inicioVigenciaDe.Value.Date));
            }

            if (fimVigenciaDe.HasValue)
            {
                criteria.Add(fimVigenciaAte.HasValue
                    ? Restrictions.Between("FimVigencia", fimVigenciaDe.Value.Date, fimVigenciaAte.Value.Date)
                    : Restrictions.Eq("FimVigencia", fimVigenciaDe.Value.Date));
            }


            list = criteria.List<Assunto>() as List<Assunto>;

            return list;
        }

        public Assunto ObterPorId(int id)
        {
            return GerenciadorBDConfigs.Instance.SessaoAtual().Get<Assunto>(id);
        }

        public Assunto ObterPorCodigo(string codigo)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Assunto))
                .Add(Restrictions.Eq("Codigo", codigo));
            return criteria.UniqueResult<Assunto>() ;
        }

        public IList<Assunto> ObterPorDescricao(string descricao)
        {
            ICriteria criteria =
                GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof (Assunto)).Add(
                    Restrictions.Like("Descricao", descricao, MatchMode.Anywhere));
            return criteria.List<Assunto>() as List<Assunto>;
            
        }

        public int ObterUltimoIdCodigoInteiro()
        {
            string[] literal = new string[] 
                {"a","b","c","d","e","f","g","h","i","j"
                ,"l","m","n","o","p","q","r","s","t","u","v","x","z","y"
                ,"w"};

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Assunto)).SetMaxResults(1);

            for (int i = 0; i <= literal.Length - 1; i++)
            {
                criteria.Add(Restrictions.Not(Restrictions.Like("Codigo", literal[i], MatchMode.Anywhere)));
            }

            criteria.AddOrder(Order.Desc("AssuntoId"));


            Assunto assunto = criteria.UniqueResult<Assunto>();
            int ultimoCodigo = assunto != null ? assunto.AssuntoId : 0;

            return ultimoCodigo;
        }
    }
}